

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.sql.Timestamp;
import java.util.ArrayList;

@SuppressWarnings("serial")
public class ServidorPasajero extends UnicastRemoteObject implements IServidorPasajero {

	private Registry registry;
	private Usuario pasajero;
	private Usuario conductor = null;
	private ArrayList<Usuario> companerosViaje;
	
	/*
	 * Inicializa el RMI server, para esperar invitaciones de conductores.
	 */
	public ServidorPasajero(String ip, int puerto, Usuario pasajero) throws RemoteException{
        super();
        this.pasajero = pasajero;
        System.out.println("this address="+pasajero.getIp()+",port="+pasajero.getPuerto());
        try{
        	registry= LocateRegistry.createRegistry(pasajero.getPuerto());
            registry.rebind("servidorPasajero", this);
        }
        catch(RemoteException e){
        	throw e;
        }
    }
	
	/**
	 * LLamado desde Conductor, para consultar si acepta o rechaza la propuesta de viaje
	 */
	public int aceptarConductor(Usuario conductor) throws RemoteException{
		this.conductor = conductor;
		if(this.pasajero.getEstado()==1){
			BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
			String respuesta="";
			
			while(respuesta.compareTo("no")!=0 && respuesta.compareTo("si")!=0){
				System.out.println("El conductor: "+conductor.getNombre()+" desea que te unas a su viaje. \nDesea viajar con el?(si/no):");
				try {
					respuesta = reader.readLine();
					if(respuesta.compareTo("si")==0){
						this.pasajero.setEstado(0);
						return 1;
					}
					else if(respuesta.compareTo("no")==0){
						this.pasajero.setEstado(1);
						return 0;
					}
					else{
						System.out.println("Error, debe ingresar si o no");
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return -1;
	}
	

	@Override
	public void coordinarViaje(ArrayList<Usuario> pasajeros){
		this.companerosViaje = pasajeros;
		String resp = "";
		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		System.out.println("Sus compañeros de viajes son:");
		
		/**
		 * Removiendo esta instancia de la lista de pasajeros (mi mismo)
		 */
		for (int i = 0; i < companerosViaje.size(); i++) {
			if(companerosViaje.get(i).getTelefono()==this.pasajero.getTelefono()){
				companerosViaje.remove(i);
			}
		}
		
		IServidorConductor conduc;
		
		Registry r;
		int respuesta ;
		
		for (int i = 0; i < companerosViaje.size(); i++) {
			System.out.println(companerosViaje.get(i).toString());
		}
		
		do{
			System.out.print("Desea comprobar si el viaje va (s/n): ");
			try {
				resp = reader.readLine();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}while(resp.compareTo("s")!=0 && resp.compareTo("n")!=0);
		
		if(resp.compareTo("s")==0){					
			try {
				 r=LocateRegistry.getRegistry(this.conductor.getIp(), (new Integer(this.conductor.getPuerto())).intValue());
				 conduc=(IServidorConductor)(r.lookup("servidorConductor"));	
				 respuesta = conduc.confirmarViaje(this.pasajero);
				 /*
				  * El viaje fue cancelado... este pasajero se encarga de confirmarle a todo el resto...
				  */
				 if(respuesta==0){
					 enviaCancelacionViaje(pasajeros);
				 }
			}catch(RemoteException e){
				System.out.println("Se perdio la conexion con conductor, cancelando viaje...");
				enviaCancelacionViaje(pasajeros);
			}catch(NotBoundException e){
				System.out.println("El servidor a contactar no existe, cancelando viaje...");
				enviaCancelacionViaje(pasajeros);
			}		   	
		}
	}
	
	private void enviaCancelacionViaje(ArrayList<Usuario> pasajeros){
		Registry r;
		IServidorPasajero companero;
		try {
			DBManager.setConductor(this.conductor.getTelefono(), 0, this.conductor.getNum_asiento()); // 
			
			System.out.println("Informando la cancelacion a compañeros de viaje...");
			for (int i = 0; i < this.companerosViaje.size(); i++) {
				try{
					r=LocateRegistry.getRegistry(this.companerosViaje.get(i).getIp(), (new Integer(this.companerosViaje.get(i).getPuerto())).intValue());
					companero=(IServidorPasajero)(r.lookup("servidorPasajero"));
					companero.cancelarViaje(this.pasajero);
					DBManager.setPasajero(this.companerosViaje.get(i).getTelefono(), 0);
				}catch(RemoteException e){
					e.printStackTrace();
				}catch(NotBoundException e){
					e.printStackTrace();
				}	
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	
	
	@Override
	public void cancelarViaje(Usuario usuario) throws RemoteException {		
		System.out.println("\n"+usuario.getNombre()+", le informa que el viaje ha sido cancelado.");
	}
	
	
	
	/*
	 * estado = 1, esta buscando auto, 0 no viaja
	 */
	@SuppressWarnings("deprecation")
	public int solicitarPasajero(Usuario conductor) throws RemoteException {
		
		if(this.pasajero.getEstado()==1){
			BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
			Timestamp timestmp = conductor.getFecha_hora();
			String respuesta="";
			
			while(respuesta.compareTo("no")!=0 && respuesta.compareTo("si")!=0){
				System.out.println("El conductor: "+conductor.getNombre()+" \ndesea que te unas a su viaje, para el dia: "+
						timestmp.getDate()+"/"+(timestmp.getMonth()+1)+", a las: "+timestmp.getHours()+":"+timestmp.getMinutes()+
						", \ndesea viajar con l?(si/no):");
				try {
					respuesta = reader.readLine();
					if(respuesta.compareTo("si")==0){
						this.pasajero.setEstado(1);
						return 0;
					}
					else if(respuesta.compareTo("no")==0){
						this.pasajero.setEstado(0);
						return -1;
					}
					else{
						System.out.println("Error, debe ingresar si o no");
					}
					this.pasajero.setEstado(0);
				} catch (IOException e) {
					e.printStackTrace();
					return 1;
				}
			}
			
		}
		return -1;
	}
		
}